home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJEMU106.ARJ / EMUMATH.CC < prev    next >
C/C++ Source or Header  |  1992-04-08  |  6KB  |  317 lines

  1. #include "emu.h"
  2. #include "const.h"
  3.  
  4. extern "C" void djshld(void *);
  5. extern "C" void djshrd(void *);
  6.  
  7. extern void normalize(reg& r);
  8.  
  9. void r_uadd(reg& a, reg& b, reg& s) // signs ignored
  10. {
  11.   reg t;
  12.   int dif = a.exp - b.exp;
  13.   if (!dif) dif = a.sigh - b.sigh;
  14.   if (!dif) dif = a.sigl - b.sigl;
  15.   if (dif > 0)
  16.   {
  17.     r_mov(a, s);
  18.     r_mov(b, t);
  19.   }
  20.   else
  21.   {
  22.     r_mov(b, s);
  23.     r_mov(a, t);
  24.   }
  25.   if (s.exp - t.exp > 64)
  26.     return;
  27.   while (t.exp < s.exp)
  28.   {
  29.     t.exp ++;
  30.     djshrd(&t.sigl);
  31.   }
  32.   unsigned short *ss, *ts;
  33.   unsigned long tmp;
  34.   ss = (unsigned short *)&s.sigl;
  35.   ts = (unsigned short *)&t.sigl;
  36.   tmp = 0;
  37.   for (int i=4; i>0; i--)
  38.   {
  39.     tmp += (unsigned long)*ss + (unsigned long)*ts;
  40.     *ss = tmp;
  41.     ss++;
  42.     ts++;
  43.     tmp >>= 16;
  44.   }
  45.   if (tmp)
  46.   {
  47.     djshrd(&s.sigl);
  48.     s.exp++;
  49.     s.sigh |= 0x80000000;
  50.   }
  51.   if (!(s.sigh | s.sigl))
  52.   {
  53.     s.exp = 0;
  54.     s.tag = TW_Z;
  55.   }
  56.   else
  57.   {
  58.     while (!(s.sigh & 0x80000000))
  59.     {
  60.       if (s.exp == 0)
  61.         return;
  62.       djshld(&s.sigl);
  63.       s.exp--;
  64.     }
  65.   }
  66. }
  67.  
  68. void r_usub(reg& a, reg& b, reg& d) // a > b
  69. {
  70.   reg t;
  71.   r_mov(a, d);
  72.   r_mov(b, t);
  73.  
  74.   if (d.exp - t.exp > 64)
  75.     return;
  76.   while (t.exp < d.exp)
  77.   {
  78.     t.exp ++;
  79.     djshrd(&t.sigl);
  80.   }
  81.   unsigned short *ss, *ts;
  82.   long tmp;
  83.   ss = (unsigned short *)&d.sigl;
  84.   ts = (unsigned short *)&t.sigl;
  85.   tmp = 0;
  86.   for (int i=4; i>0; i--)
  87.   {
  88.     tmp += (long)*ss - (long)*ts;
  89.     *ss = tmp;
  90.     ss++;
  91.     ts++;
  92.     tmp >>= 16;
  93.   }
  94.   if (!(d.sigh | d.sigl))
  95.   {
  96.     d.exp = 0;
  97.     d.tag = TW_Z;
  98.   }
  99.   else
  100.   {
  101.     while (!(d.sigh & 0x80000000))
  102.     {
  103.       if (d.exp == 0)
  104.         return;
  105.       djshld(&d.sigl);
  106.       d.exp--;
  107.     }
  108.   }
  109. }
  110.  
  111. void r_add(reg& a, reg& b, reg& s)
  112. {
  113.   char old_sign;
  114.   if (a.tag == TW_Z)
  115.     return r_mov(b, s);
  116.   if (b.tag == TW_Z)
  117.     return r_mov(a, s);
  118.   if (a.tag == TW_S)
  119.     return r_mov(a, s);
  120.   if (b.tag == TW_S)
  121.     return r_mov(b, s);
  122.  
  123.   switch (a.sign*2 + b.sign)
  124.   {
  125.     case 0: // P + P
  126.     case 3: // N + N
  127.       r_uadd(a, b, s);
  128.       s.sign = a.sign;
  129.       break;
  130.     case 1: // P + N
  131.       old_sign = b.sign;
  132.       b.sign ^= SIGN_POS^SIGN_NEG;
  133.       r_sub(a, b, s);
  134.       b.sign = old_sign;
  135.       break;
  136.     case 2: // N + P
  137.       old_sign = a.sign;
  138.       a.sign ^= SIGN_POS^SIGN_NEG;
  139.       r_sub(b, a, s);
  140.       a.sign = old_sign;
  141.       break;
  142.   }
  143. }
  144.  
  145. void r_sub(reg& a, reg& b, reg& d)
  146. {
  147.   if (b.tag == TW_Z)
  148.     return r_mov(a, d);
  149.   if (a.tag == TW_Z)
  150.   {
  151.     r_mov(b, d);
  152.     d.sign ^= SIGN_POS^SIGN_NEG;
  153.     return;
  154.   }
  155.   if (a.tag == TW_S)
  156.     return r_mov(a, d);
  157.   if (b.tag == TW_S)
  158.   {
  159.     r_mov(b, d);
  160.     d.sign ^= SIGN_POS^SIGN_NEG;
  161.     return;
  162.   }
  163.  
  164.   int mdif;
  165.   mdif = a.exp - b.exp;
  166.   if (!mdif)
  167.     mdif = a.sigh - b.sigh;
  168.   if (!mdif)
  169.     mdif = a.sigl - b.sigl;
  170.  
  171.   switch (a.sign*2 + b.sign)
  172.   {
  173.     case 0: // P - P
  174.     case 3: // N - N
  175.       if (mdif > 0)
  176.       {
  177.         r_usub(a, b, d);
  178.         d.sign = a.sign;
  179.       }
  180.       else
  181.       {
  182.         r_usub(b, a, d);
  183.         d.sign = a.sign ^ SIGN_POS^SIGN_NEG;
  184.       }
  185.       break;
  186.     case 1: // P - N
  187.       r_uadd(a, b, d);
  188.       d.sign = SIGN_POS;
  189.       break;
  190.     case 2: // N - P
  191.       r_uadd(a, b, d);
  192.       d.sign = SIGN_NEG;
  193.       break;
  194.   }
  195. }
  196.  
  197. void r_mul(reg& a, reg& b, reg& s)
  198. {
  199.   if (a.tag == TW_Z)
  200.   {
  201.     r_mov(CONST_Z, s);
  202.   }
  203.   else if (b.tag == TW_Z)
  204.   {
  205.     r_mov(CONST_Z, s);
  206.   }
  207.   else if (a.tag == TW_S)
  208.   {
  209.     r_mov(a, s);
  210.   }
  211.   else if (b.tag == TW_S)
  212.   {
  213.     r_mov(b, s);
  214.   }
  215.   else
  216.   {
  217.     unsigned short sl[9], carry[10];
  218.     unsigned short *as = (unsigned short *)(&a.sigl);
  219.     unsigned short *bs = (unsigned short *)(&b.sigl);
  220.     unsigned long l, sum;
  221.     int ai, bi;
  222.     for (ai=0; ai<8; ai++)
  223.       sl[ai] = carry[ai] = 0;
  224.     for (ai = 0; ai < 4; ai++)
  225.       for (bi = 0; bi < 4; bi++)
  226.       {
  227.         l = as[ai] * bs[bi];
  228.  
  229.         sum = sl[ai+bi] + (l & 0xffff);
  230.         sl[ai+bi] = sum & 0xffff;
  231.  
  232.         sum = sl[ai+bi+1] + (l>>16) + (sum>>16);
  233.         sl[ai+bi+1] = sum & 0xffff;
  234.  
  235.         carry[ai+bi+2] += sum>>16;
  236.       }
  237.     for (ai=0; ai<8; ai++)
  238.     {
  239.       if (carry[ai])
  240.       {
  241.         sum = sl[ai] + carry[ai];
  242.         sl[ai] = sum & 0xffff;
  243.         carry[ai+1] += sum>>16;
  244.       }
  245.     }
  246.     s.sigl = *(long *)(sl+4);
  247.     s.sigh = *(long *)(sl+6);
  248.     s.exp = a.exp + b.exp - EXP_BIAS + 1;
  249.     s.tag = TW_V;
  250.   }
  251.   if (a.sign == b.sign)
  252.     s.sign = SIGN_POS;
  253.   else
  254.     s.sign = SIGN_NEG;
  255.   normalize(s);
  256. }
  257.  
  258. void r_div(reg& a, reg& b, reg& q)
  259. {
  260.   if (a.tag == TW_S)
  261.   {
  262.     if (val_same(a, CONST_PINF))
  263.       r_mov(a, q);
  264.     else if (val_same(a, CONST_NINF))
  265.       r_mov(a, q);
  266.   }
  267.   else if (b.tag == TW_S)
  268.   {
  269.     if (val_same(b, CONST_PINF))
  270.       r_mov(CONST_Z, q);
  271.     else if (val_same(b, CONST_NINF))
  272.       r_mov(CONST_Z, q);
  273.   }
  274.   else if (a.tag == TW_Z)
  275.   {
  276.     r_mov(a, q);
  277.   }
  278.   else if (b.tag == TW_Z)
  279.   {
  280.     exception(EX_Z);
  281.   }
  282.   else
  283.   {
  284.     q.exp = a.exp - b.exp + EXP_BIAS;
  285.     if (q.exp > EXP_MAX)
  286.       r_mov(CONST_PINF, q);
  287.     else if (q.exp <= 0)
  288.       r_mov(CONST_Z, q);
  289.     else
  290.     {
  291.       unsigned long long al, bl, ql, f;
  292.       int i;
  293.       al = *(unsigned long long *)(&a.sigl);
  294.       bl = *(unsigned long long *)(&b.sigl);
  295.       ql = 0;
  296.       f = (unsigned long long)1 << 63;
  297.       for (i=0; i<64; i++)
  298.       {
  299.         if (al >= bl)
  300.         {
  301.           al -= bl;
  302.           ql += f;
  303.         }
  304.         bl >>= 1;
  305.         f >>= 1;
  306.       }
  307.       *(unsigned long long *)(&q.sigl) = ql;
  308.       q.tag = TW_V;
  309.     }
  310.   }
  311.   if (a.sign == b.sign)
  312.     q.sign = SIGN_POS;
  313.   else
  314.     q.sign = SIGN_NEG;
  315.   normalize(q);
  316. }
  317.